package com.mmall.service;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.mmall.dao.SysAclMapper;
import com.mmall.dao.SysAclModuleMapper;
import com.mmall.dao.SysDeptMapper;
import com.mmall.dto.AclDto;
import com.mmall.dto.AclModuleLevelDto;
import com.mmall.dto.DeptLevelDto;
import com.mmall.model.SysAcl;
import com.mmall.model.SysAclModule;
import com.mmall.model.SysDept;
import com.mmall.util.LevelUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by asus on 2018/3/30.
 */
@Service
public class SysTreeService {

    @Resource
    private SysDeptMapper sysDeptMapper;
    @Resource
    private SysAclModuleMapper sysAclModuleMapper;
    @Resource
    private SysCoreService sysCoreService;
    @Resource
    private SysAclMapper sysAclMapper;

    //部门树
    public List<DeptLevelDto> deptTree(){
        List<SysDept> deptList = sysDeptMapper.getAllDept();
        List<DeptLevelDto> dtoList = Lists.newArrayList();
        for(SysDept dept:deptList){
            DeptLevelDto dto = DeptLevelDto.adapt(dept);
            dtoList.add(dto);
        }
        return deptListToTree(dtoList);
    }
    //部门列表转成部门树
    public List<DeptLevelDto> deptListToTree(List<DeptLevelDto> deptLevelList){
        if(CollectionUtils.isEmpty(deptLevelList)){
            return Lists.newArrayList();
        }
        Multimap<String, DeptLevelDto> levelDeptMap = ArrayListMultimap.create();
        List<DeptLevelDto> rootList = Lists.newArrayList();
        //遍历dto列表
        for(DeptLevelDto dto : deptLevelList){
            levelDeptMap.put(dto.getLevel(),dto);
            if(LevelUtil.ROOT.equals(dto.getLevel())){
                rootList.add(dto);
            }
        }
        //按照seq从小到大进行排序
        Collections.sort(rootList, new Comparator<DeptLevelDto>() {
            public int compare(DeptLevelDto o1, DeptLevelDto o2) {
                return o1.getSeq()-o2.getSeq();
            }
        });
        //递归生成树
        transformDeptTree(rootList,LevelUtil.ROOT,levelDeptMap);
        return rootList;
    }
    //递归转成部门树
    public void transformDeptTree(List<DeptLevelDto> deptLevelList,String level,Multimap<String, DeptLevelDto> levelDeptMap){
        for(int i = 0;i<deptLevelList.size();i++){
            //遍历当前层的每个元素
            DeptLevelDto deptLevelDto = deptLevelList.get(i);
            //得到下一层级的值
            String nextLevel = LevelUtil.calculateLevel(level,deptLevelDto.getId());
            //下一层级的部门列表
            List<DeptLevelDto> tempDeptList = (List<DeptLevelDto>)levelDeptMap.get(nextLevel);
            if(CollectionUtils.isNotEmpty(tempDeptList)){
                //对下一层级列表排序
                Collections.sort(tempDeptList,deptSeqComparator);
                //设置为上一层级的下层
                deptLevelDto.setDeptList(tempDeptList);
                //递归处理下一层
                transformDeptTree(tempDeptList,nextLevel,levelDeptMap);
            }
        }
    }

    //部门比较器
    public Comparator<DeptLevelDto> deptSeqComparator = new Comparator<DeptLevelDto>() {
        public int compare(DeptLevelDto o1, DeptLevelDto o2) {
            return o1.getSeq() - o2.getSeq();
        }
    };

    //权限模块比较器
    public Comparator<AclModuleLevelDto> aclModuleSeqComparator = new Comparator<AclModuleLevelDto>() {
        public int compare(AclModuleLevelDto o1, AclModuleLevelDto o2) {
            return o1.getSeq() - o2.getSeq();
        }
    };

    //权限点比较器
    public Comparator<AclDto> aclSeqComparator = new Comparator<AclDto>() {
        public int compare(AclDto o1, AclDto o2) {
            return o1.getSeq() - o2.getSeq();
        }
    };

    //权限部门树
    public List<AclModuleLevelDto> aclModuleTree(){
        List<AclModuleLevelDto> dtoList = Lists.newArrayList();
        List<SysAclModule> aclModuleList= sysAclModuleMapper.getAllAclModule();
        for(SysAclModule sysAclModule : aclModuleList){
            AclModuleLevelDto dto = AclModuleLevelDto.adapt(sysAclModule);
            dtoList.add(dto);
        }
        return aclModuleListToTree(dtoList);
    }
    //权限模块列表转为部门树
    public List<AclModuleLevelDto> aclModuleListToTree(List<AclModuleLevelDto> aclModuleList){
        if(CollectionUtils.isEmpty(aclModuleList)){
            return Lists.newArrayList();
        }

        Multimap<String,AclModuleLevelDto> levelAclModuleMap = ArrayListMultimap.create();
        List<AclModuleLevelDto> rootList = new ArrayList<AclModuleLevelDto>();

        for(AclModuleLevelDto dto : aclModuleList){
            levelAclModuleMap.put(dto.getLevel(),dto);
            if(LevelUtil.ROOT.equals(dto.getLevel())){
                rootList.add(dto);
            }
        }

        Collections.sort(rootList, new Comparator<AclModuleLevelDto>() {
            public int compare(AclModuleLevelDto o1, AclModuleLevelDto o2) {
                return o1.getSeq() - o2.getSeq();
            }
        });
        //
        transformAclModuleTree(rootList,LevelUtil.ROOT,levelAclModuleMap);
        return rootList;
    }

    //权限模块递归方法
    public void transformAclModuleTree(List<AclModuleLevelDto> aclModuleLevelList,String level,Multimap<String,AclModuleLevelDto> levelAclModuleMap){
        for(int i = 0;i < aclModuleLevelList.size();i++){
            AclModuleLevelDto dto = aclModuleLevelList.get(i);
            String nextLevel = LevelUtil.calculateLevel(level,dto.getId());
            List<AclModuleLevelDto> tempAclModuleList = (List<AclModuleLevelDto>)levelAclModuleMap.get(nextLevel);
            if(CollectionUtils.isNotEmpty(tempAclModuleList)){
                Collections.sort(tempAclModuleList,aclModuleSeqComparator);
                dto.setAclModuleList(tempAclModuleList);
                transformAclModuleTree(tempAclModuleList,nextLevel,levelAclModuleMap);
            }
        }
    }

    public List<AclModuleLevelDto> roleTree(Integer roleId){

        List<SysAcl> userAclList = sysCoreService.getCurrentUserAclList();
        List<SysAcl> roleAclList = sysCoreService.getRoleAclList(roleId);

        Set<Integer> userAclIdSet = userAclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet());
        Set<Integer> roleAclIdSet = roleAclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet());

        List<AclDto> dtoList = Lists.newArrayList();
        List<SysAcl> aclList = sysAclMapper.getAll();
        for(SysAcl acl : aclList){
            AclDto aclDto = AclDto.adapt(acl);
            if(userAclIdSet.contains(aclDto.getId())){
                aclDto.setHasAcl(true);
            }
            if(roleAclIdSet.contains(aclDto.getId())){
                aclDto.setChecked(true);
            }
            dtoList.add(aclDto);
        }
        return aclListToTree(dtoList);
    }

    public List<AclModuleLevelDto> aclListToTree(List<AclDto> dtoList){
        if(CollectionUtils.isEmpty(dtoList)){
            return Lists.newArrayList();
        }
        List<AclModuleLevelDto> aclModuleLevelDtoList = aclModuleTree();

        Multimap<Integer,AclDto> aclDtoMultimap = ArrayListMultimap.create();
        for(AclDto aclDto : dtoList){
            if(aclDto.getStatus()==1){
                aclDtoMultimap.put(aclDto.getAclModuleId(),aclDto);
            }
        }
        bindAclsWithOrder(aclModuleLevelDtoList,aclDtoMultimap);
        return aclModuleLevelDtoList;
    }

    public void bindAclsWithOrder(List<AclModuleLevelDto> aclModuleLevelDtoList,Multimap<Integer,AclDto> aclDtoMultimap){
        if(CollectionUtils.isEmpty(aclModuleLevelDtoList)){
            return;
        }
        for(AclModuleLevelDto aclModuleLevelDto : aclModuleLevelDtoList){
            List<AclDto> aclDtoList = (List<AclDto>)aclDtoMultimap.get(aclModuleLevelDto.getId());
            if(CollectionUtils.isNotEmpty(aclDtoList)){
                Collections.sort(aclDtoList,aclSeqComparator);
                aclModuleLevelDto.setAclList(aclDtoList);
            }
            bindAclsWithOrder(aclModuleLevelDto.getAclModuleList(),aclDtoMultimap);
        }
    }

    public List<AclModuleLevelDto> userAclTree(int userId) {
        List<SysAcl> userAclList = sysCoreService.getUserAclList(userId);
        List<AclDto> aclDtoList = Lists.newArrayList();
        for (SysAcl acl : userAclList) {
            AclDto dto = AclDto.adapt(acl);
            dto.setHasAcl(true);
            dto.setChecked(true);
            aclDtoList.add(dto);
        }
        return aclListToTree(aclDtoList);
    }

}
